package com.virjar.dungproxy.server.proxyservice.client; import com.virjar.dungproxy.server.entity.Proxy; import com.virjar.dungproxy.server.proxyservice.client.listener.DefaultRequestExecutor; import com.virjar.dungproxy.server.proxyservice.client.listener.RequestExecutorProxy; import com.virjar.dungproxy.server.proxyservice.client.listener.ResponseListener; import com.virjar.dungproxy.server.proxyservice.client.listener.NettyConnectionsPool; import com.virjar.dungproxy.server.proxyservice.common.util.Executors; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.ssl.OpenSsl; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslProvider; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import org.jboss.netty.util.HashedWheelTimer; import org.jboss.netty.util.Timer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.KeyManagerFactory; import java.io.Closeable; import java.io.IOException; import java.security.KeyStore; public class NettyHttpClient implements Closeable { private static final Logger log = LoggerFactory.getLogger(NettyHttpClient.class); private int defaultReadTimeoutMs = 5000; private int defaultRequestTimeoutMs = 15000; private int defaultConnectionTimeoutMs = 2000; private int defaultWriteBufferLowWaterMark = 262144; private int defaultWriteBufferHighWaterMark = 524288; private EventLoopGroup defaultExecutor; private SslContext sslContext; private NettyConnectionsPool connectionsPool; public NettyHttpClient(int readTimeoutMs, int requestTimeoutMs, int connectionTimeoutMs, int writeBufferLowWaterMark, int writeBufferHighWaterMark, SslContext sslContext, NioEventLoopGroup defaultExecutor, NettyConnectionsPool connectionsPool) { this.defaultReadTimeoutMs = readTimeoutMs; this.defaultRequestTimeoutMs = requestTimeoutMs; this.defaultConnectionTimeoutMs = connectionTimeoutMs; this.defaultWriteBufferLowWaterMark = writeBufferLowWaterMark; this.defaultWriteBufferHighWaterMark = writeBufferHighWaterMark; this.sslContext = sslContext; this.connectionsPool = connectionsPool; this.defaultExecutor = defaultExecutor; } public NettyHttpClient() throws Exception { //默认配置参数 this.defaultReadTimeoutMs = 300000; this.defaultRequestTimeoutMs = 60000; this.defaultConnectionTimeoutMs = 2000; this.defaultWriteBufferLowWaterMark = 262144; this.defaultWriteBufferHighWaterMark = 524288; this.sslContext = getSslContext(); this.defaultExecutor = Executors.workerGroup; this.connectionsPool = new NettyConnectionsPool(100, 1000, 60000, -1, true, newNettyTimer()); } private static Timer newNettyTimer() { HashedWheelTimer timer = new HashedWheelTimer(); timer.start(); return timer; } private SslContext getSslContext() throws Exception { KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(NettyHttpClient.class.getResourceAsStream("/lingtong.keystore"), "225588".toCharArray()); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(keyStore, "225588".toCharArray()); return buildingSslContext(keyManagerFactory); } private SslContext buildingSslContext(KeyManagerFactory keyManagerFactory) throws javax.net.ssl.SSLException { SslContextBuilder sslContextBuilder = SslContextBuilder.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE) .keyManager(keyManagerFactory); if (!OpenSsl.isAvailable()) { log.info("OpenSSL provider not available, falling back to JDK SSL provider"); sslContextBuilder.sslProvider(SslProvider.JDK); } else { sslContextBuilder.sslProvider(SslProvider.OPENSSL); } return sslContextBuilder.build(); } public RequestBuilder prepare( FullHttpRequest request, ResponseListener listener, Proxy proxyServer) { return new RequestBuilder(request, listener, proxyServer, connectionsPool); } @Override public void close() throws IOException { defaultExecutor.shutdownGracefully().awaitUninterruptibly(); connectionsPool.destroy(); } public class RequestBuilder { private FullHttpRequest request; private Proxy proxyServer; private ResponseListener listener; private EventLoopGroup executor = defaultExecutor; private int readTimeoutMs = defaultReadTimeoutMs; private int requestTimeoutMs = defaultRequestTimeoutMs; private int connectionTimeoutMs = defaultConnectionTimeoutMs; private int writeBufferLowWaterMark = defaultWriteBufferLowWaterMark; private int writeBufferHighWaterMark = defaultWriteBufferHighWaterMark; private NettyConnectionsPool connectionsPool; private boolean customAuth = false; private boolean retry; public RequestBuilder(FullHttpRequest request, ResponseListener listener, Proxy proxyServer, NettyConnectionsPool connectionsPool) { this.request = request; this.listener = listener; this.proxyServer = proxyServer; this.connectionsPool = connectionsPool; } public void setReadTimeoutMs(int readTimeoutMs) { this.readTimeoutMs = readTimeoutMs; } public void setRequestTimeoutMs(int requestTimeoutMs) { this.requestTimeoutMs = requestTimeoutMs; } public void setConnectionTimeoutMs(int connectionTimeoutMs) { this.connectionTimeoutMs = connectionTimeoutMs; } public void setExecutor(EventLoopGroup executor) { this.executor = executor; } public void setWriteBufferLowWaterMark(int writeBufferLowWaterMark) { this.writeBufferLowWaterMark = writeBufferLowWaterMark; } public void setWriteBufferHighWaterMark(int writeBufferHighWaterMark) { this.writeBufferHighWaterMark = writeBufferHighWaterMark; } public void setConnectionsPool(NettyConnectionsPool connectionsPool) { this.connectionsPool = connectionsPool; } public void setCustomAuth(boolean customAuth) { this.customAuth = customAuth; } public void setRetry(boolean retry) { this.retry = retry; } public RequestExecutorProxy execute() { return new DefaultRequestExecutor( readTimeoutMs, requestTimeoutMs, connectionTimeoutMs, writeBufferLowWaterMark, writeBufferHighWaterMark, executor, request, listener, sslContext, proxyServer, connectionsPool, customAuth, retry ).execute(); } } }